#include "pch.h"
#include "CDicomImage.h"
//#include "Vector4.h"
#include "Utilities.h"


CDicomImage::CDicomImage()
	: CBaseImage()
{
}


CDicomImage::~CDicomImage()
{
	
}

BOOL CDicomImage::ParseFile(std::string fn)
{
	std::lock_guard<std::mutex> lg(m_mtx);
	if (!m_parser.Open(fn))
		return FALSE;

	CString charset = m_parser.GetTagValue(0x0008, 0x0005);

	BOOL needTransToGbk = FALSE;
	if (charset == _T("ISO_IR 192"))
		needTransToGbk = TRUE;

	CString tmp;
	std::string strVal;

	// Patient
	m_patInfo.patId = m_parser.GetTagValue(0x0010, 0x0020);
	strVal = m_parser.GetTagStringValue(0x0010, 0x0010);
	if (needTransToGbk)
		m_patInfo.patName = UTF8toA(strVal).c_str();
	else
		m_patInfo.patName = strVal.c_str();
		
	m_patInfo.sex = m_parser.GetTagValue(0x0010, 0x0040);
	tmp = m_parser.GetTagValue(0x0010, 0x0030);
	if (tmp.GetLength() == 8)
	{
		m_patInfo.birthday = tmp.Left(4);
		m_patInfo.birthday += _T("-");
		m_patInfo.birthday += tmp.Mid(4, 2);
		m_patInfo.birthday += _T("-");
		m_patInfo.birthday += tmp.Mid(6);
	}
	else
		m_patInfo.birthday = tmp;

	m_patInfo.studyAge = m_parser.GetTagValue(0x0010, 0x1010);
	m_patInfo.patWeight = m_parser.GetTagFloatValue(0x0010, 0x1030);

	// Study
	m_studyInfo.modality = m_parser.GetTagValue(0x0008, 0x0060);
	m_studyInfo.studyInsUid = m_parser.GetTagValue(0x0020, 0x000D);
	strVal = m_parser.GetTagStringValue(0x0008, 0x1030);
	if (needTransToGbk)
		m_studyInfo.studyDesc = UTF8toA(strVal).c_str();
	else
		m_studyInfo.studyDesc = strVal.c_str();

	m_studyInfo.studyId = m_parser.GetTagValue(0x0020, 0x0010);
	m_studyInfo.accessionNumber = m_parser.GetTagValue(0x0008, 0x0050);

	tmp = m_parser.GetTagValue(0x0008, 0x0020);
	if (tmp.GetLength() == 8)
	{
		m_studyInfo.studyDate = tmp.Left(4);
		m_studyInfo.studyDate += _T("-");
		m_studyInfo.studyDate += tmp.Mid(4, 2);
		m_studyInfo.studyDate += _T("-");
		m_studyInfo.studyDate += tmp.Mid(6);
	}
	else
		m_studyInfo.studyDate = tmp;

	tmp = m_parser.GetTagValue(0x0008, 0x0030);
	if (tmp.GetLength() >= 6)
	{
		m_studyInfo.studyTime = tmp.Left(2);
		m_studyInfo.studyTime += _T(":");
		m_studyInfo.studyTime += tmp.Mid(2, 2);
		m_studyInfo.studyTime += _T(":");
		m_studyInfo.studyTime += tmp.Mid(4);
	}
	else
		m_studyInfo.studyTime = tmp;
	
	strVal = m_parser.GetTagStringValue(0x0008, 0x0070);
	if (needTransToGbk)
		m_studyInfo.manufacturer = UTF8toA(strVal).c_str();
	else
		m_studyInfo.manufacturer = strVal.c_str();

	strVal = m_parser.GetTagStringValue(0x0008, 0x0080);
	if (needTransToGbk)
		m_studyInfo.hospitalName = UTF8toA(strVal).c_str();
	else
		m_studyInfo.hospitalName = strVal.c_str();
	
	strVal = m_parser.GetTagStringValue(0x0008, 0x0081);
	if (needTransToGbk)
		m_studyInfo.hospitalAddr = UTF8toA(strVal).c_str();
	else
		m_studyInfo.hospitalAddr = strVal.c_str();

	strVal = m_parser.GetTagStringValue(0x0008, 0x1070);
	if (needTransToGbk)
		m_studyInfo.operatorName = UTF8toA(strVal).c_str();
	else
		m_studyInfo.operatorName = strVal.c_str();

	// Series
	m_seriesInfo.seriesInsUid = m_parser.GetTagValue(0x0020, 0x000E);
	strVal = m_parser.GetTagStringValue(0x0008, 0x103E);
	if (needTransToGbk)
		m_seriesInfo.seriesDesc = UTF8toA(strVal).c_str();
	else
		m_seriesInfo.seriesDesc = strVal.c_str();

	tmp = m_parser.GetTagValue(0x0008, 0x0021);
	if (tmp.GetLength() == 8)
	{
		m_seriesInfo.seriesDate = tmp.Left(4);
		m_seriesInfo.seriesDate += _T("-");
		m_seriesInfo.seriesDate += tmp.Mid(4, 2);
		m_seriesInfo.seriesDate += _T("-");
		m_seriesInfo.seriesDate += tmp.Mid(6);
	}
	else
		m_seriesInfo.seriesDate = tmp;

	tmp = m_parser.GetTagValue(0x0008, 0x0031);
	if (tmp.GetLength() >= 6)
	{
		m_seriesInfo.seriesTime = tmp.Left(2);
		m_seriesInfo.seriesTime += _T(":");
		m_seriesInfo.seriesTime += tmp.Mid(2, 2);
		m_seriesInfo.seriesTime += _T(":");
		m_seriesInfo.seriesTime += tmp.Mid(4);
	}
	else
		m_seriesInfo.seriesTime = tmp;

	m_seriesInfo.seriesNumber = m_parser.GetTagIntValue(0x0020, 0x0011);

	// CT
	m_seriesInfo.kvp = m_parser.GetTagValue(0x0018, 0x0060);
	m_seriesInfo.exposureTime = m_parser.GetTagValue(0x0018, 0x1150);
	m_seriesInfo.xRayTubeCurrent = m_parser.GetTagValue(0x0018, 0x1151);
	m_seriesInfo.exposure = m_parser.GetTagValue(0x0018, 0x1152);

	// MR
	m_seriesInfo.percentFOV = m_parser.GetTagValue(0x0018, 0x0094);
	m_seriesInfo.TR = m_parser.GetTagValue(0x0018, 0x0080);
	m_seriesInfo.TE = m_parser.GetTagValue(0x0018, 0x0081);
	m_seriesInfo.FS = m_parser.GetTagValue(0x0018, 0x0087);
	m_seriesInfo.amiX = m_parser.GetTagIntValue(0x0018, 0x1310, 0);
	m_seriesInfo.amiY = m_parser.GetTagIntValue(0x0018, 0x1310, 1);
	m_seriesInfo.amjX = m_parser.GetTagIntValue(0x0018, 0x1310, 2);
	m_seriesInfo.amjY = m_parser.GetTagIntValue(0x0018, 0x1310, 3);
	m_seriesInfo.protocolName = m_parser.GetTagValue(0x0018, 0x1030);
	m_seriesInfo.scanSequence = m_parser.GetTagValue(0x0018, 0x0020);

	// Image
	m_imageInfo.ipX = m_parser.GetTagFloatValue(0x0020, 0x0032, 0);
	m_imageInfo.ipY = m_parser.GetTagFloatValue(0x0020, 0x0032, 1);
	m_imageInfo.ipZ = m_parser.GetTagFloatValue(0x0020, 0x0032, 2);
	m_imageInfo.ioiX = m_parser.GetTagFloatValue(0x0020, 0x0037, 0);
	m_imageInfo.ioiY = m_parser.GetTagFloatValue(0x0020, 0x0037, 1);
	m_imageInfo.ioiZ = m_parser.GetTagFloatValue(0x0020, 0x0037, 2);
	m_imageInfo.iojX = m_parser.GetTagFloatValue(0x0020, 0x0037, 3);
	m_imageInfo.iojY = m_parser.GetTagFloatValue(0x0020, 0x0037, 4);
	m_imageInfo.iojZ = m_parser.GetTagFloatValue(0x0020, 0x0037, 5);
	m_imageInfo.poX = m_parser.GetTagValue(0x0020, 0x0020, 0);
	m_imageInfo.poY = m_parser.GetTagValue(0x0020, 0x0020, 1);
	m_imageInfo.patPosition = m_parser.GetTagValue(0x0018, 0x5100);
	m_imageInfo.sliceThickness = m_parser.GetTagValue(0x0018, 0x0050);
	m_imageInfo.sliceLocation = m_parser.GetTagValue(0x0020, 0x1041);
	m_imageInfo.samplePerPixel = m_parser.GetTagIntValue(0x0028, 0x0002);

	m_imageInfo.psX = m_parser.GetTagFloatValue(0x0018, 0x1164, 0);
	m_imageInfo.psY = m_parser.GetTagFloatValue(0x0018, 0x1164, 1);
	if (m_imageInfo.psX == 0.0 || m_imageInfo.psY == 0.0) {
		m_imageInfo.psX = m_parser.GetTagFloatValue(0x0028, 0x0030, 0);
		m_imageInfo.psY = m_parser.GetTagFloatValue(0x0028, 0x0030, 1);
	}

	m_imageInfo.bitsAlloc = m_parser.GetTagIntValue(0x0028, 0x0100);
	m_imageInfo.bitsStored = m_parser.GetTagIntValue(0x0028, 0x0101);
	m_imageInfo.hightBit = m_parser.GetTagIntValue(0x0028, 0x0102);
	m_imageInfo.pixelRep = m_parser.GetTagIntValue(0x0028, 0x0103);
	m_imageInfo.defWinCenter = m_parser.GetTagFloatValue(0x0028, 0x1050);
	m_imageInfo.defWinWidth = m_parser.GetTagFloatValue(0x0028, 0x1051);
	if (m_imageInfo.defWinCenter==0.0 && m_imageInfo.defWinWidth==0.0)
	{

	}
	m_imageInfo.rescaleIntercept = m_parser.GetTagFloatValue(0x0028, 0x1052);
	m_imageInfo.rescaleSlope = m_parser.GetTagFloatValue(0x0028, 0x1053);
	m_imageInfo.height = m_parser.GetTagIntValue(0x0028, 0x0010);
	m_imageInfo.width = m_parser.GetTagIntValue(0x0028, 0x0011);
	m_imageInfo.instanceNumber = m_parser.GetTagIntValue(0x0020, 0x0013);

	m_imageInfo.sopInsUid = m_parser.GetTagValue(0x0008, 0x0018);
	m_imageInfo.xfer = m_parser.GetTagValue(0x0002, 0x0010);
	m_imageInfo.imageType = m_parser.GetTagValue(0x0008, 0x0008);
	m_imageInfo.charset = charset;

	tmp = m_parser.GetTagValue(0x0008, 0x0023);
	if (tmp.GetLength() == 8)
	{
		m_imageInfo.contentDate = tmp.Left(4);
		m_imageInfo.contentDate += _T("-");
		m_imageInfo.contentDate += tmp.Mid(4, 2);
		m_imageInfo.contentDate += _T("-");
		m_imageInfo.contentDate += tmp.Mid(6);
	}
	else
		m_imageInfo.contentDate = tmp;

	tmp = m_parser.GetTagValue(0x0008, 0x0033);
	if (tmp.GetLength() >= 6)
	{
		m_imageInfo.contentTime = tmp.Left(2);
		m_imageInfo.contentTime += _T(":");
		m_imageInfo.contentTime += tmp.Mid(2, 2);
		m_imageInfo.contentTime += _T(":");
		m_imageInfo.contentTime += tmp.Mid(4);
	}
	else
		m_imageInfo.contentTime = tmp;

	tmp = m_parser.GetTagValue(0x0008, 0x0022);
	if (tmp.GetLength() == 8)
	{
		m_imageInfo.acquisitionDate = tmp.Left(4);
		m_imageInfo.acquisitionDate += _T("-");
		m_imageInfo.acquisitionDate += tmp.Mid(4, 2);
		m_imageInfo.acquisitionDate += _T("-");
		m_imageInfo.acquisitionDate += tmp.Mid(6);
	}
	else
		m_imageInfo.acquisitionDate = tmp;

	tmp = m_parser.GetTagValue(0x0008, 0x0032);
	if (tmp.GetLength() >= 6)
	{
		m_imageInfo.acquisitionTime = tmp.Left(2);
		m_imageInfo.acquisitionTime += _T(":");
		m_imageInfo.acquisitionTime += tmp.Mid(2, 2);
		m_imageInfo.acquisitionTime += _T(":");
		m_imageInfo.acquisitionTime += tmp.Mid(4);
	}
	else
		m_imageInfo.acquisitionTime = tmp;

	if (m_seriesInfo.seriesDate.IsEmpty())
		m_seriesInfo.seriesDate = m_imageInfo.acquisitionDate;

	if (m_seriesInfo.seriesTime.IsEmpty())
		m_seriesInfo.seriesTime = m_imageInfo.acquisitionTime;

	m_nImgSize = m_parser.GetImageSize();
	m_bParserValid = m_parser.HasImage();
	m_fileName = fn;

	Close();

	return TRUE;
}

void CDicomImage::GetDefaultWindow(double& wc, double& ww)
{
	m_parser.GetDefaultWindow(wc, ww);
}

void CDicomImage::GetRange(double& minVal, double& maxVal)
{
	m_parser.GetRange(minVal, maxVal);
}

void* CDicomImage::CreateThumbnail(int& width, int& height)
{
	void* pThumb = NULL;
	if (!m_bParserValid)
	{
		if (ReParseFile())
		{
			pThumb = m_parser.CreateThumbnail(width, height);
			Close();
		}
	}
	else
	{
		pThumb = m_parser.CreateThumbnail(width, height);
		Close();
	}

	return pThumb;
}

BOOL CDicomImage::CreateDIB(void*& pdib, int& w, int& h, int wc, int ww, int frame/* = 0*/, bool bneg/* = false*/, bool bov/* = true*/)
{
	if (pdib)
	{
		delete[]pdib;
		pdib = NULL;
	}

	if (!m_bParserValid)
		ReParseFile();

	return m_parser.CreateDIB(pdib, w, h, wc, ww, frame, bneg, bov);
}


int CDicomImage::GetFrameCount()
{
	return m_parser.GetFrameCount();
}

void CDicomImage::Close()
{
	std::lock_guard<std::mutex> lg(m_parsermtx);
	if (m_parser.GetFrameCount() > 1)
		return;

	m_parser.Close();
	m_nImgSize = 0;
	m_bParserValid = FALSE;
}

BOOL CDicomImage::ReParseFile()
{
	std::lock_guard<std::mutex> lg(m_parsermtx);
	if (m_bParserValid)
		return TRUE;

	if (m_fileName.empty())
		return FALSE;

	if (!m_parser.Open(m_fileName))
		return FALSE;

	m_nImgSize = m_parser.GetImageSize();
	//m_bParserValid = m_parser.HasImage();
	m_bParserValid = m_parser.IsValid();

	return m_bParserValid;
}

void CDicomImage::GetTagList(std::vector<DcmTagInfo>& vec)
{
	if (!IsValid()) 
		ReParseFile();

	m_parser.GetTagList(vec);
}

void CDicomImage::GetMeasureInfo(MeasureInfo& info, int type, std::vector<Gdiplus::PointF>* vecPts /*= NULL*/)
{
	if (!IsValid()) ReParseFile();

	m_parser.GetMeasureInfo(info, type, vecPts);
}

bool CDicomImage::Export(std::string dst, int format)
{	
	if (!IsValid()) ReParseFile();
	return m_parser.Export(dst, format);
}

double CDicomImage::GetLocation()
{
	return 0.0;
	////if (!IsValid())
	////	return 0.0;

	//CVector4 v1, v2, v, pt;
	//v1.SetValue(GetImageInfo().ioiX, GetImageInfo().ioiY, GetImageInfo().ioiZ, 0);
	//v2.SetValue(GetImageInfo().iojX, GetImageInfo().iojY, GetImageInfo().iojZ, 0);

	//if (v1.Norm() < FLT_EPSILON || v2.Norm() < FLT_EPSILON)
	//	return 0.0;

	//CVector4 k(0, 0, 1, 0);
	//if (abs(k.Dot(v2)) > 0.6)
	//	v = v2.Cross(v1);
	//else
	//	v = v1.Cross(v2);

	//pt.SetValue(GetImageInfo().ipX, GetImageInfo().ipY, GetImageInfo().ipZ, 1.0);
	//double pos = v.Dot(pt);

	//return pos;
}
